package com.qm.console.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.green.model.v20180509.ImageSyncScanRequest;
import com.aliyuncs.green.model.v20180509.VideoAsyncScanResultsRequest;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.green.model.v20180509.VideoAsyncScanRequest;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;

import java.io.UnsupportedEncodingException;
import java.util.*;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoRequest;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * //                       _oo0oo_
 * //                      o8888888o
 * //                      88" . "88
 * //                      (| -_- |)
 * //                      0\  =  /0
 * //                    ___/`---'\___
 * //                  .' \\|     |// '.
 * //                 / \\|||  :  |||// \
 * //                / _||||| -:- |||||- \
 * //               |   | \\\  -  /// |   |
 * //               | \_|  ''\---/''  |_/ |
 * //               \  .-\__  '-'  ___/-. /
 * //             ___'. .'  /--.--\  `. .'___
 * //          ."" '<  `.___\_<|>_/___.' >' "".
 * //         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 * //         \  \ `_.   \_ __\ /__ _/   .-` /  /
 * //     =====`-.____`.___ \_____/___.-`___.-'=====
 * //                       `=---='
 * //
 * //
 * //     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * //
 * //               佛祖保佑         永无BUG
 * <p>
 * com.qm.console.utils
 * Created on 2020/7/30.
 */
@Component
@Slf4j
public class AliSafetyUtils {

    private static final String ACCESS_KEY = "LTAI4G7gKbqrZDkDEw1LXHA5";

    private static final String KEY_SECRET = "p1eX4hH7GymRZLfnhkUFMQlU2P7rAt";

    private DefaultAcsClient CLIENT;


    @PostConstruct
    private void init() {
        String regionId = "ap-southeast-1";  // 点播服务接入区域
        DefaultProfile profile = DefaultProfile.getProfile(regionId, ACCESS_KEY, KEY_SECRET);
        CLIENT = new DefaultAcsClient(profile);
    }


    /**
     * @param url
     * @return 正常图片返回0, porn图片返回评分，错误返回-1
     */
    public float badImageIdentify(String url) {

        ImageSyncScanRequest imageSyncScanRequest = new ImageSyncScanRequest();
        // 指定API返回格式。
        imageSyncScanRequest.setAcceptFormat(FormatType.JSON);
        // 指定请求方法。
        imageSyncScanRequest.setMethod(MethodType.POST);
        imageSyncScanRequest.setEncoding("utf-8");
        //支持HTTP和HTTPS。
        imageSyncScanRequest.setProtocol(ProtocolType.HTTP);

        JSONObject httpBody = new JSONObject();
        /**
         * 设置要检测的风险场景。计费依据此处传递的场景计算。
         * 一次请求中可以同时检测多张图片，每张图片可以同时检测多个风险场景，计费按照场景计算。
         * 例如：检测2张图片，场景传递porn和terrorism，计费会按照2张图片鉴黄，2张图片暴恐检测计算。
         * porn：表示鉴黄场景。
         */
        httpBody.put("scenes", Arrays.asList("porn", "ad"));

        /**
         * 设置待检测图片。一张图片对应一个task。
         * 多张图片同时检测时，处理的时间由最后一个处理完的图片决定。
         * 通常情况下批量检测的平均响应时间比单张检测的要长。一次批量提交的图片数越多，响应时间被拉长的概率越高。
         * 这里以单张图片检测作为示例, 如果是批量图片检测，请自行构建多个task。
         */
        JSONObject task = new JSONObject();
        task.put("dataId", UUID.randomUUID().toString());

        //设置图片链接。
        task.put("url", url);
        task.put("time", new Date());
        httpBody.put("tasks", Arrays.asList(task));

        imageSyncScanRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(httpBody.toJSONString()),
                "UTF-8", FormatType.JSON);

        /**
         * 请设置超时时间。服务端全链路处理超时时间为10秒，请做相应设置。
         * 如果您设置的ReadTimeout小于服务端处理的时间，程序中会获得一个read timeout异常。
         */
        imageSyncScanRequest.setConnectTimeout(3000);
        imageSyncScanRequest.setReadTimeout(10000);
        HttpResponse httpResponse = null;
        try {
            httpResponse = CLIENT.doAction(imageSyncScanRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //服务端接收到请求，完成处理后返回的结果。
        if (httpResponse != null && httpResponse.isSuccess()) {
            JSONObject scrResponse = JSON.parseObject(org.apache.commons.codec.binary.StringUtils.newStringUtf8(httpResponse.getHttpContent()));
            System.out.println(JSON.toJSONString(scrResponse, true));
            int requestCode = scrResponse.getIntValue("code");
            //每一张图片的检测结果。
            JSONArray taskResults = scrResponse.getJSONArray("data");
            if (200 == requestCode) {
                for (Object taskResult : taskResults) {
                    //单张图片的处理结果。
                    int taskCode = ((JSONObject) taskResult).getIntValue("code");
                    //图片对应检测场景的处理结果。如果是多个场景，则会有每个场景的结果。
                    JSONArray sceneResults = ((JSONObject) taskResult).getJSONArray("results");
                    if (200 == taskCode) {
                        float maxRate = 0;
                        for (Object sceneResult : sceneResults) {
                            String scene = ((JSONObject) sceneResult).getString("scene");
//                            String suggestion = ((JSONObject) sceneResult).getString("suggestion");
                            float rate = ((JSONObject) sceneResult).getFloat("rate");
                            String label = ((JSONObject) sceneResult).getString("label");
                            if (StringUtils.equals(scene, "porn") && StringUtils.equals(label, "porn")) {
                                if (rate > maxRate) {
                                    maxRate = rate;
                                }
                            } else if (StringUtils.equals(scene, "ad") && !StringUtils.equals(label, "normal")) {
                                if (rate > maxRate) {
                                    maxRate = rate;
                                }
                            }
                        }
                        return maxRate;
                    } else {
                        //单张图片处理失败, 原因视具体的情况详细分析。
                        log.error("task process fail, response: {}", JSON.toJSONString(taskResult));
                    }
                }
            } else {
                /**
                 * 表明请求整体处理失败，原因视具体的情况详细分析。
                 */
                log.error("image scan request failed, response: {}", JSON.toJSONString(scrResponse));
            }
        }
        log.error("failed to get porn result, url: {}", url);
        return -1;
    }

    /**
     * @param url
     * @return 正常视频返回0, porn图片返回评分，错误返回-1
     */
    public float badVideoIdentify(String url) {
        VideoAsyncScanRequest videoAsyncScanRequest = new VideoAsyncScanRequest();
        videoAsyncScanRequest.setAcceptFormat(FormatType.JSON); // 指定API返回格式。
        videoAsyncScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); // 指定请求方法。

        List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
        Map<String, Object> task = new LinkedHashMap<String, Object>();
        task.put("dataId", UUID.randomUUID().toString());
        task.put("url", url);
        task.put("interval", 2);

        tasks.add(task);
        /**
         * 设置要检测的场景。计费是依据此处传递的场景计算。
         * 视频默认1秒截取一帧，您可以自行控制截帧频率。收费按照视频的截帧数量以及每一帧的检测场景计算。
         * 举例：1分钟的视频截帧60张，检测色情（对应场景参数porn）和暴恐涉政（对应场景参数terrorism）2个场景，收费按照60张色情+60张暴恐涉政进行计费。
         */
        JSONObject data = new JSONObject();
        data.put("scenes", Arrays.asList("porn", "ad"));
        data.put("tasks", tasks);

        videoAsyncScanRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(data.toJSONString()),
                "UTF-8", FormatType.JSON);
        /**
         * 请务必设置超时时间。
         */
        videoAsyncScanRequest.setConnectTimeout(3000);
        videoAsyncScanRequest.setReadTimeout(6000);
        try {
            HttpResponse httpResponse = CLIENT.doAction(videoAsyncScanRequest);

            if(httpResponse.isSuccess()){
                JSONObject jsonObject = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
                JSONArray dataArray = jsonObject.getJSONArray("data");
                JSONObject dataObject = (JSONObject) dataArray.get(0);
                JSONObject results = this.VideoResults(dataObject.getString("taskId"));
                JSONArray resultsArray = results.getJSONArray("results");
                float maxRate = 0;
                for (Object sceneResult : resultsArray) {
                    String scene = ((JSONObject) sceneResult).getString("scene");
//                            String suggestion = ((JSONObject) sceneResult).getString("suggestion");
                    float rate = ((JSONObject) sceneResult).getFloat("rate");
                    String label = ((JSONObject) sceneResult).getString("label");
                    if (StringUtils.equals(scene, "porn") && StringUtils.equals(label, "porn")) {
                        if (rate > maxRate) {
                            maxRate = rate;
                        }
                    } else if (StringUtils.equals(scene, "ad") && !StringUtils.equals(label, "normal")) {
                        if (rate > maxRate) {
                            maxRate = rate;
                        }
                    }
                }
                return maxRate;
            }else{
                System.out.println("response not success. status:" + httpResponse.getStatus());
            }
        } catch (ServerException | UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * @param taskId
     * @return JSONObject
     */
    private JSONObject VideoResults(String taskId){
        // 通过轮询查询视频结果
        VideoAsyncScanResultsRequest videoAsyncScanResultsRequest = new VideoAsyncScanResultsRequest();
        videoAsyncScanResultsRequest.setAcceptFormat(FormatType.JSON);

        List<String> taskList = new ArrayList<String>();
        // 这里添加要查询的taskId。提交任务的时候需要自行保存taskId。
        taskList.add(taskId);
        videoAsyncScanResultsRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(JSON.toJSONString(taskList)),
                "UTF-8", FormatType.JSON);
        /**
         * 请务必设置超时时间。
         */
        videoAsyncScanResultsRequest.setConnectTimeout(3000);
        videoAsyncScanResultsRequest.setReadTimeout(6000);
        while (true){
            try {
                HttpResponse httpResponse = CLIENT.doAction(videoAsyncScanResultsRequest);
                if(httpResponse.isSuccess()){
                    JSONObject jsonObject = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
                    JSONArray dataArray = jsonObject.getJSONArray("data");
                    JSONObject dataObject = (JSONObject) dataArray.get(0);
                    if(dataObject.getInteger("code") == 200){
                        System.out.println(JSON.toJSONString(jsonObject, true));
                        return dataObject;
                    }
                    Thread.sleep(1000);
                    System.out.println("PROCESSING - queue");
                }else{
                    System.out.println("response not success. status:" + httpResponse.getStatus());
                }
            } catch (ServerException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getMediaUrl(String playId, String playType) {
        GetPlayInfoRequest request = new GetPlayInfoRequest();
        request.setVideoId(playId);
        request.setFormats(playType);
        String url = null;

        try {
            GetPlayInfoResponse response = CLIENT.getAcsResponse(request);
            List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();
            //播放地址
            List<String> playInfos = playInfoList.stream().map(GetPlayInfoResponse.PlayInfo::getPlayURL).collect(Collectors.toList());
            if (playInfos != null && playInfos.size() > 0) {
                url = playInfos.get(0);
//                videoPalyVo.setPlayInfo(playInfos.get(0));
            } else {
                throw new Exception();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return url;
    }

}
